package com.jackstraw.jack_base.datasource.elasticsearch.repository;

import co.elastic.clients.elasticsearch._types.FieldValue;
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.json.JsonData;
import com.jackstraw.jack_base.datasource.elasticsearch.entity.bean.ElasticSearchRouting;
import com.jackstraw.jack_base.datasource.elasticsearch.entity.Product;
import com.jackstraw.jack_base.util.CollectionUtil;
import com.jackstraw.jack_base.util.DateTimeUtil;
import com.jackstraw.jack_base.util.ObjectUtil;
import com.jackstraw.jack_base.util.StringUtil;
import com.jackstraw.jack_base.util.function.ReflectionUtil;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

public class ProductElasticsearchRepository extends ElasticsearchRepository<Product> {


    public ProductElasticsearchRepository(ElasticSearchRouting elasticSearchRouting, Class<Product> entityClass) {
        super(elasticSearchRouting, entityClass);
    }

    @Override
    public BoolQuery.Builder boolQueryBuilder(Product entity, BoolQuery.Builder boolQueryBuilder) {
        //条件判断（若没有条件时，抛出异常）
        Boolean queryFlag = Boolean.TRUE;
        boolQueryBuilder = super.boolQueryBuilder(entity, boolQueryBuilder);
        if (ObjectUtil.ObjectUtilByLang3.isEmpty(boolQueryBuilder)) {
            queryFlag = Boolean.FALSE;
            boolQueryBuilder = new BoolQuery.Builder();
        }


        String titleNot = entity.getTitleNot();
        if (StringUtil.StringUtilsBylang3.isNotEmpty(titleNot)) {
            queryFlag = Boolean.TRUE;
            boolQueryBuilder.mustNot(mn -> mn.term(m
                    -> m.field(ReflectionUtil.getFieldName(Product::getTitle))
                    .value(titleNot)));
        }

        List<String> categoryList = entity.getCategoryList();
        if (CollectionUtil.isNotEmpty(categoryList)) {
            queryFlag = Boolean.TRUE;
            boolQueryBuilder.must(m
                    -> m.terms(t
                    -> t.field(ReflectionUtil.getFieldName(Product::getCategory))
                    .terms(tv
                            -> tv.value(categoryList
                            .stream().map(category
                                    -> FieldValue.of(category)).collect(Collectors.toList())))));
        }

        String categoryNot = entity.getCategoryNot();
        if (StringUtil.StringUtilsBylang3.isNotEmpty(categoryNot)) {
            queryFlag = Boolean.TRUE;
            boolQueryBuilder.mustNot(mn -> mn.term(m
                    -> m.field(ReflectionUtil.getFieldName(Product::getCategory))
                    .value(categoryNot)));
        }

        Double priceMax = entity.getPriceMax();
        if (ObjectUtil.ObjectUtilByLang3.isNotEmpty(priceMax)) {
            queryFlag = Boolean.TRUE;
            boolQueryBuilder.must(m
                    -> m.range(r
                    -> r.field(ReflectionUtil.getFieldName(Product::getPrice))
                    .lte(JsonData.of(priceMax))));
        }

        Double priceMin = entity.getPriceMin();
        if (ObjectUtil.ObjectUtilByLang3.isNotEmpty(priceMin)) {
            queryFlag = Boolean.TRUE;
            boolQueryBuilder.must(m
                    -> m.range(r
                    -> r.field(ReflectionUtil.getFieldName(Product::getPrice))
                    .gt(JsonData.of(priceMin))));
        }


        Date createDateMax = entity.getCreateDateMax();
        if (ObjectUtil.ObjectUtilByLang3.isNotEmpty(createDateMax)) {
            queryFlag = Boolean.TRUE;
            boolQueryBuilder.must(m
                    -> m.range(r
                    -> r.field(ReflectionUtil.getFieldName(Product::getCreateDate))
                    .lt(JsonData.of(JsonData.of(DateTimeUtil.format(createDateMax, DateTimeUtil.NORM_DATETIME_MS_PATTERN))))));
        }


        Date createDateMin = entity.getCreateDateMin();
        if (ObjectUtil.ObjectUtilByLang3.isNotEmpty(createDateMin)) {
            queryFlag = Boolean.TRUE;
            boolQueryBuilder.must(m
                    -> m.range(r
                    -> r.field(ReflectionUtil.getFieldName(Product::getCreateDate))
                    .gte(JsonData.of(DateTimeUtil.format(createDateMin, DateTimeUtil.NORM_DATETIME_MS_PATTERN)))));
        }


        return queryFlag ? boolQueryBuilder : null;
    }
}
